package com.nineclock.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nineclock.common.constant.NcConstant;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.utils.CurrentUserHolder;
import com.nineclock.system.dto.SysAdminDTO;
import com.nineclock.system.dto.SysChangeAdminDTO;
import com.nineclock.system.dto.SysCompanyDTO;
import com.nineclock.system.dto.SysUserDTO;
import com.nineclock.system.mapper.SysCompanyMapper;
import com.nineclock.system.mapper.SysCompanyUserMapper;
import com.nineclock.common.aliyun.oss.OSSUtils;
import com.nineclock.system.mapper.SysCompanyUserRoleMapper;
import com.nineclock.system.mapper.SysRoleMapper;
import com.nineclock.system.pojo.SysCompany;
import com.nineclock.system.pojo.SysCompanyUser;
import com.nineclock.system.pojo.SysCompanyUserRole;
import com.nineclock.system.pojo.SysRole;
import com.nineclock.system.service.CompanyService;
import com.nineclock.system.service.SmsService;
import com.nineclock.system.vo.SysCompanyVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.UUID;

import static com.nineclock.common.constant.SMSConstant.SMS_TYPE_RESET_PASSWORD;

/**
 * @author yangchao
 * @create 2022-01-13 9:30
 **/
@Transactional
@Service
public class CompanyServiceImpl extends ServiceImpl<SysCompanyMapper,SysCompany> implements CompanyService {

    @Autowired
    private OSSUtils ossUtils;

    @Autowired
    private SysCompanyUserMapper sysCompanyUserMapper;

    @Autowired
    private SysCompanyUserRoleMapper sysCompanyUserRoleMapper;

    @Autowired
    private SysCompanyMapper sysCompanyMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SmsService smsService;

    /**
     * 查询当前用户信息所在公司的信息
     */
    @Override
    public SysCompanyVO findCompany() {

        //判断用户是否登录
        if(CurrentUserHolder.get() == null){
            throw new NcException(ResponseEnum.UNAUTHORIZED);
        }

        //获取当前登录用户的企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();

        //找到相应信息
        SysCompany sysCompany = this.getById(companyId);

        //将需要的属性封装为VO类
        SysCompanyVO sysCompanyVO = new SysCompanyVO();
        BeanUtils.copyProperties(sysCompany,sysCompanyVO);

        //查询并返回企业相应的信息
        return sysCompanyVO;

    }

    /**
     * 上传公司图片logo
     * @param file
     * @return
     */
    @Override
    public String uploadCompanyImg(MultipartFile file) {

        //判断用户是否登录
        if(CurrentUserHolder.get() == null){
            throw new NcException(ResponseEnum.UNAUTHORIZED);
        }

        //检查文件类型是否符合要求
        String type = file.getContentType();
        if(!NcConstant.ALLOWED_IMG_TYPES.contains(type)){
            throw new NcException(ResponseEnum.INVALID_FILE_TYPE);
        }

        //检查文件大小是否超过限制
        long size = file.getSize();
        if(size > NcConstant.maxFileSize){
            throw new NcException(ResponseEnum.FILE_SIZE_EXCEED_MAX_LIMIT);
        }

        //获取原始文件名
        String originalFilename = file.getOriginalFilename();
        //获取文件后缀
        String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));

        //生成文件名
        String fileName = UUID.randomUUID().toString() + suffixName;

        //图片地址
        String url = "";

        try {
            InputStream inputStream = file.getInputStream();

            url = ossUtils.uploadImgFile(fileName, inputStream);

        } catch (IOException e) {
            e.printStackTrace();
        }

        return url;
    }

    /**
     * 修改当前用户的企业信息
     * @param sysCompanyDTO
     */
    @Override
    public void updateCompany(SysCompanyDTO sysCompanyDTO) {

        //判断参数是否为有效参数
        if(sysCompanyDTO == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //判断用户是否登录
        if(CurrentUserHolder.get() == null){
            throw new NcException(ResponseEnum.UNAUTHORIZED);
        }

        //获取当前登录用户的企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();

        //获取原有公司的信息
        SysCompany company = this.getById(companyId);
        String logo = company.getLogo();
        //删除原有的公司图片
        String substring = logo.substring(logo.lastIndexOf("/") + 1);
        ossUtils.deleteImgFile(substring);

        SysCompany sysCompany = new SysCompany();
        BeanUtils.copyProperties(sysCompanyDTO,sysCompany);
        sysCompany.setId(companyId);

        //修改企业的信息
        this.updateById(sysCompany);

        //修改
        LambdaQueryWrapper<SysCompanyUser> lambdaQueryWrapper = new LambdaQueryWrapper<SysCompanyUser>().eq(SysCompanyUser::getCompanyId, companyId);
        SysCompanyUser sysCompanyUser = new SysCompanyUser();
        sysCompanyUser.setCompanyName(sysCompanyDTO.getName());
        sysCompanyUser.setUpdateTime(new Date());

        //批量修改
        sysCompanyUserMapper.update(sysCompanyUser,lambdaQueryWrapper);

    }

    /**
     * 获取企业当前主管理员
     */
    @Override
    public SysAdminDTO getCurrentAdmin() {

        //判断用户是否登录
        if(CurrentUserHolder.get() == null){
            throw new NcException(ResponseEnum.UNAUTHORIZED);
        }

        //获取当前用户ID
        Long companyId = CurrentUserHolder.get().getCompanyId();

        //获取用户管理员常量
        String adminRoleSys = NcConstant.ADMIN_ROLE_SYS;

        return sysCompanyMapper.selectSystemAdmin(companyId, adminRoleSys);

    }

    /**
     * 更改系统管理员
     * @param sysChangeAdminDTO
     */
    @Override
    public void changeSystemAdmin(SysChangeAdminDTO sysChangeAdminDTO) {

        //判断参数合法性
        if(sysChangeAdminDTO == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //判断用户是否登录
        if(CurrentUserHolder.get() == null){
            throw new NcException(ResponseEnum.UNAUTHORIZED);
        }

        //判断当前新管理员的数据是否存在
        //获取新管理员的Id
        Long newAdminId = sysChangeAdminDTO.getUserId();
        SysCompanyUser sysCompanyUser = sysCompanyUserMapper.selectOne(new LambdaQueryWrapper<SysCompanyUser>()
                .eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId())
                .eq(SysCompanyUser::getId, newAdminId));

        if(sysCompanyUser == null){
            throw new NcException(ResponseEnum.COMPANY_ADMIN_NOT_EXISTS);
        }

        //判断传递的手机验证码是否正确
        smsService.verifySMSMessage(sysChangeAdminDTO.getCode(),sysCompanyUser.getMobile(),SMS_TYPE_RESET_PASSWORD);

        //解绑原有的系统管理员与员工的关系
        //获取当前企业的主管理员信息
        //获取当前用户ID
        Long companyId = CurrentUserHolder.get().getCompanyId();

        //获取用户管理员常量
        String adminRoleSys = NcConstant.ADMIN_ROLE_SYS;

        //查询老管理员ID
        SysAdminDTO sysAdminDTO = sysCompanyMapper.selectSystemAdmin(companyId, adminRoleSys);
        Long oldAdminUserId = sysAdminDTO.getUserId();

        //更改老员工的职位为职员：ROLE_USER_EMPLOYEE
        updateEmployeePosition(oldAdminUserId,"ROLE_USER_EMPLOYEE",companyId);

        //添加新的系统管理员与员工的关系
        updateEmployeePosition(sysCompanyUser.getUserId(),adminRoleSys,companyId);

    }

    /**
     * 更改员工职位
     *
     * @param employeeId 要更改的员工Id
     * @param roleName 要改为的职位名称
     * @param companyId 所在企业的Id
     */
    private void updateEmployeePosition(Long employeeId,String roleName,Long companyId){

        LambdaQueryWrapper<SysCompanyUser> lambdaQueryWrapper = new LambdaQueryWrapper<SysCompanyUser>().eq(SysCompanyUser::getCompanyId, companyId)
                .eq(SysCompanyUser::getUserId, employeeId);
        //查询关联表Id
        Long id = sysCompanyUserMapper.selectOne(lambdaQueryWrapper).getId();

        SysCompanyUserRole sysCompanyUserRole = new SysCompanyUserRole();

        //将该员工的职位降为 roleName
        Long role_user_employeeId = sysRoleMapper.selectOne(new LambdaQueryWrapper<SysRole>()
                .eq(SysRole::getRoleName, roleName).eq(SysRole::getCompanyId,companyId))
                .getId();

        sysCompanyUserRole.setRoleId(role_user_employeeId);

        sysCompanyUserRoleMapper.update(sysCompanyUserRole,new LambdaQueryWrapper<SysCompanyUserRole>().eq(SysCompanyUserRole::getCompanyUserId,id));

    }

}
